/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.core;
import java.net.URL;
import java.util.Enumeration;
import org.openide.filesystems.*;
import org.openide.execution.NbClassLoader;
import org.openide.util.WeakListener;
/** Classloader for the filesystem pool. Attaches itself as a listener to
* each file a class has been loaded from. If such a file is deleted, modified
* or renamed clears the global variable that holds "current" classloader, so
* on next request for current one new is created.
*
* @author Jaroslav Tulach
*/
class ClassLoaderSupport extends NbClassLoader
implements FileChangeListener, RepositoryListener {
/** change listener */
private FileChangeListener listener;
/** the pool */
private static Repository pool = NbTopManager.getDefaultRepository ();
/** holds current classloader (or null if not created yet) */
private static ClassLoaderSupport current;
/** @return the current classloader for the system */
static ClassLoader currentClassLoader () {
ClassLoader c = current;
if (c == null) {
c = createClassLoader ();
}
return c;
}
/** Creates new classloader. Synchronized to allow only
* one access the current at time.
*/
synchronized static ClassLoader createClassLoader () {
if (current == null) {
current = new ClassLoaderSupport ();
}
return current;
}
/** Resets the loader.
*/
synchronized static void resetLoader () {
if (current != null) {
current = null;
}
}
/** Constructor that attaches itself to the filesystem pool.
*/
public ClassLoaderSupport () {
Repository rep = NbTopManager.getDefaultRepository ();
rep.addRepositoryListener (WeakListener.repository (this, rep));
listener = WeakListener.fileChange (this, null);
}
/** When looking for a file, register listener on its changes.
* @param name of the class
* @return the Class or null
*/
protected Class findClass (String name) throws ClassNotFoundException {
Class c = super.findClass (name);
if (c != null) {
FileObject fo;
int lastDot = name.lastIndexOf ('.');
if (lastDot == -1) {
fo = pool.find ("", name, "class"); // NOI18N
} else {
fo = pool.find (name.substring (0, lastDot), name.substring (lastDot + 1), "class"); // NOI18N
}
if (fo != null) {
// if the file is from the file system pool,
// register to catch its changes
fo.addFileChangeListener (listener);
}
}
return c;
}
/** Tests whether this object is current loader and if so,
* clears the loader.
* @param fo file object that initiated the action
*/
private void test (FileObject fo) {
if (current == this) {
reset ();
}
fo.removeFileChangeListener (listener);
}
/** Resets the loader, removes it from listneing on all known objects.
*/
private synchronized void reset () {
if (current == this) {
current = null;
}
}
/** If this object is not current classloader, removes it from
* listening on given file object.
*/
private void testRemove (FileObject fo) {
if (current != this) {
fo.removeFileChangeListener (listener);
}
}
/** Called when new file system is added to the pool.
* @param ev event describing the action
*/
public void fileSystemAdded (RepositoryEvent ev) {
reset ();
}
/** Called when a file system is deleted from the pool.
* @param ev event describing the action
*/
public void fileSystemRemoved (RepositoryEvent ev) {
reset ();
}
/** Resets the loader.
*/
public void fileSystemPoolReordered (RepositoryReorderedEvent ev) {
reset ();
}
/** Fired when a new folder has been created. This action can only be
* listened in folders containing the created file up to the root of
* file system.
*
* @param fe the event describing context where action has taken place
*/
public void fileFolderCreated (FileEvent fe) {
testRemove (fe.getFile ());
}
/** Fired when a new file has been created. This action can only be
* listened in folders containing the created file up to the root of
* file system.
*
* @param fe the event describing context where action has taken place
*/
public void fileDataCreated (FileEvent fe) {
testRemove (fe.getFile ());
}
/** Fired when a file has been changed.
* @param fe the event describing context where action has taken place
*/
public void fileChanged (FileEvent fe) {
test (fe.getFile ());
}
/** Fired when a file has been deleted.
* @param fe the event describing context where action has taken place
*/
public void fileDeleted (FileEvent fe) {
test (fe.getFile ());
}
/** Fired when a file has been renamed.
* @param fe the event describing context where action has taken place
* and the original name and extension.
*/
public void fileRenamed (FileRenameEvent fe) {
test (fe.getFile ());
}
/** Fired when a file attribute has been changed.
* @param fe the event describing context where action has taken place,
* the name of attribute and old and new value.
*/
public void fileAttributeChanged (FileAttributeEvent fe) {
testRemove (fe.getFile ());
}
}
/*
* Log
* 11 Gandalf 1.10 1/13/00 Jaroslav Tulach I18N
* 10 Gandalf 1.9 11/5/99 Jaroslav Tulach WeakListener has now
* registration methods.
* 9 Gandalf 1.8 10/27/99 Petr Hrebejk Testing of modules added
* 8 Gandalf 1.7 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 7 Gandalf 1.6 6/10/99 Jaroslav Tulach Updates the loaders when
* the file is modified.
* 6 Gandalf 1.5 6/8/99 Ian Formanek ---- Package Change To
* org.openide ----
* 5 Gandalf 1.4 3/26/99 Jaroslav Tulach
* 4 Gandalf 1.3 3/19/99 Jaroslav Tulach TopManager.getDefault
* ().getRegistry ()
* 3 Gandalf 1.2 2/11/99 Ian Formanek Renamed FileSystemPool ->
* Repository
* 2 Gandalf 1.1 1/12/99 Jaroslav Tulach Modules are loaded by
* URLClassLoader
* 1 Gandalf 1.0 1/5/99 Ian Formanek
* $
*/